home *** CD-ROM | disk | FTP | other *** search
- /*
- * grafix --- egagraf.c
- *
- * EGA graphics driver - hi-res mode only (on enhanced, ordinary, or
- * mono (i hope it works!) display)
- *
- * Written 4/87 by Scott Snyder (ssnyder@romeo.caltech.edu or @citromeo.bitnet)
- *
- */
-
- #include <dos.h>
- #include "macros.h"
- #include "grafsys.h"
-
- /* EGA parameters */
-
- #define int_video 16
- #define ega_setmode 0
- #define ega_setcur 2
- #define ega_setpage 5
- #define ega_writech 9
- #define ega_setpal 0x10
- #define mde_80bw 2
- #define mde_80co 3
- #define mde_320 4
- #define mde_640 6
- #define mde_640X200c 14
- #define mde_640X350m 15
- #define mde_640X350c 16
-
- #define g_linsiz 80
- #define g_allmask 0xff
- #define g_pixbyte 8
- #define g_bitpix 1
-
- /* Display dependent parameters */
-
- #define g_en_pg1 (g_obj far *)0xa0000000
- #define g_en_pg2 (g_obj far *)0xa0008000
- #define g_en_bufsiz 28000
- #define g_en_colormask 0x0f
- #define g_en_xsize 640
- #define g_en_ysize 350
- #define g_en_xchsize (g_en_xsize / 8)
- #define g_en_ychsize (g_en_ysize / 14)
- #define g_en_aspect 0.85
-
- #define g_cd_pg1 (g_obj far *)0xa0000000
- #define g_cd_pg2 (g_obj far *)0xa0004000
- #define g_cd_bufsiz 16000
- #define g_cd_colormask 0x0f
- #define g_cd_xsize 640
- #define g_cd_ysize 200
- #define g_cd_xchsize (g_cd_xsize / 8)
- #define g_cd_ychsize (g_cd_ysize / 8)
- #define g_cd_aspect 0.43
-
- #define g_mo_pg1 (g_obj far *)0xa0000000
- #define g_mo_pg2 (g_obj far *)0xa0008000 /* is this right??? */
- #define g_mo_bufsiz 28000
- #define g_mo_colormask 0x03
- #define g_mo_xsize 640
- #define g_mo_ysize 350
- #define g_mo_xchsize (g_mo_xsize / 8)
- #define g_mo_ychsize (g_mo_ysize / 14)
- #define g_mo_aspect 0.85
-
- /* EGA port and register addresses */
-
- #define ega_gr_addr 0x3ce /* graphics controller address register */
- #define ega_gr_data 0x3cf /* graphics controller data register */
- #define ega_gr_sr 0 /* set/reset register index */
- #define ega_gr_sren 1 /* set/reset enable register index */
- #define ega_gr_ccmp 2 /* color compare register index */
- #define ega_gr_rot 3 /* data rotate */
- #define ega_gr_mapsel 4 /* read map select */
- #define ega_gr_mode 5 /* mode register */
- #define ega_gr_misc 6 /* miscellaneous */
- #define ega_gr_colorx 7 /* color don't care */
- #define ega_gr_mask 8 /* bit mask */
- #define ega_gr_x_xor 24 /* xor function select */
-
- /* mode variables */
-
- STATIC unsigned g_bufsiz;
- STATIC unsigned g_colormask;
- STATIC g_obj far *g_page1addr, far *g_page2addr;
-
- /* utility macros */
-
- #define swap(a, b) {int _tmp; _tmp=a; a=b; b=_tmp;}
- #define trimcolor(c) c &= g_colormask
-
- #define plot(ptr, mask, tmp) { /* plot a pt. grph addr. must be mask reg */ \
- outp(ega_gr_data, mask); \
- tmp = *ptr; /* a read and a write that will STAY HERE!! */\
- *ptr = 0; \
- }
-
- /* move one to right */
- #define bumpx(ptr,mask) \
- if ((mask >>= g_bitpix) == 0) { \
- mask = 0x80; \
- ptr++; \
- }
-
- /* move one line */
- #define bumpy(ptr,ydir) { \
- if (ydir) \
- ptr-=g_linsiz; \
- else \
- ptr+=g_linsiz; \
- }
-
- /****************************************************************************\
- * internal utilities *
- \****************************************************************************/
-
- /* calculate byte and bit offsets in the graphics buffer for a point */
-
- STATIC void goffs(x, y, offs, pix)
- unsigned x, y, *offs, *pix;
- {
- *offs = y*g_linsiz + x/g_pixbyte;
- *pix = g_pixbyte - 1 - x%g_pixbyte;
- }
-
- /****************************************************************************
- * externally callable functions *
- ****************************************************************************/
-
- /* fill a region with the specified color */
-
- #ifdef __TURBOC__
- # pragma warn -aus /* TC */
- # pragma warn -rch
- #endif
- void EGA_regfill(x1, y1, x2, y2, c)
- unsigned x1, y1, x2, y2, c;
- {
- unsigned offs1, offs2, pix1, pix2;
- int wholeobjs;
- g_obj far *ptr1, far *ptr2;
- g_obj begmask, endmask, mask;
- register unsigned y;
- register g_obj far *p;
- register g_obj tmp;
-
- if (y2 < y1) swap(y1, y2);
- if (x2 < x1) swap(x1, x2);
-
- goffs(x1, y1, &offs1, &pix1);
- goffs(x2, y1, &offs2, &pix2);
- wholeobjs = offs2 - offs1 - 1;
- ptr1 = g_drawbuf + offs1;
- ptr2 = g_drawbuf + offs2;
-
- trimcolor(c);
- begmask = g_allmask >> (g_pixbyte - 1 - pix1)*g_bitpix;
- endmask = g_allmask << pix2*g_bitpix;
-
- /* set up EGA registers for write */
-
- outp(ega_gr_addr, ega_gr_sr); /* set/reset register */
- outp(ega_gr_data, c);
- outp(ega_gr_addr, ega_gr_sren); /* set/reset enable register */
- outp(ega_gr_data, g_colormask);
- outp(ega_gr_addr, ega_gr_mode); /* mode register */
- outp(ega_gr_data, 0); /* write mode 0 */
- outp(ega_gr_addr, ega_gr_mask); /* select bit mask register */
-
- /* do the write */
-
- if (wholeobjs < 0) { /* region is less than 8 pels wide */
- p = ptr1;
- mask = begmask & endmask;
- outp(ega_gr_data, mask); /* set bitmask for writes */
- for (y=y1; y<=y2; y++) {
- tmp = *p; /* read byte into latches */
- *p = 0; /* then write there to set the */
- /* bits */
- bumpy(p, 0);
- }
- }
- else {
- p = ptr1; /* do left edge */
- outp(ega_gr_data, begmask);
- for (y=y1; y<=y2; y++) {
- tmp = *p;
- *p = 0;
- bumpy(p, 0);
- }
-
- p = ptr2; /* do right egde */
- outp(ega_gr_data, endmask);
- for (y=y1; y<=y2; y++) {
- tmp = *p;
- *p = 0;
- bumpy(p, 0);
- }
-
- p = ptr1+1; /* now fill it in */
- outp(ega_gr_data, g_allmask);
- for (y=y1; y<=y2; y++) {
- g_fmemset(p, g_allmask, wholeobjs); /* can write it with anything here */
- bumpy(p, 0);
- }
- }
-
- /* reset the EGA to something nice */
-
- outp(ega_gr_data, g_allmask); /* reset bit mask */
- outp(ega_gr_addr, ega_gr_sren); /* disable set/reset mode */
- outp(ega_gr_data, 0);
- }
- #ifdef __TURBOC__
- # pragma warn .aus /* TC */
- # pragma warn .rch
- #endif
-
- /* fill the entire buffer with a color fast */
-
- void EGA_clearall(c)
- unsigned c;
- {
- /* set up EGA registers for write */
-
- outp(ega_gr_addr, ega_gr_sr); /* set/reset register */
- outp(ega_gr_data, c);
- outp(ega_gr_addr, ega_gr_sren); /* set/reset enable register */
- outp(ega_gr_data, g_colormask);
- outp(ega_gr_addr, ega_gr_mode); /* mode register */
- outp(ega_gr_data, 0); /* write mode 0 */
-
- g_fmemset(g_drawbuf, g_allmask, g_bufsiz);
-
- outp(ega_gr_addr, ega_gr_sren); /* disable set/reset mode */
- outp(ega_gr_data, 0);
- }
-
- /* make the drawing buffer visible by switching pages */
-
- void EGA_show()
- {
- union REGS inregs, outregs;
-
- if (g_bufflg) {
- g_curpage = 1-g_curpage;
- inregs.h.ah = ega_setpage;
- inregs.h.al = g_curpage;
- int86(int_video, &inregs, &outregs);
-
- g_drawbuf = g_physbuf; /* swap around buffer pointers */
- g_physbuf = g_virtbuf;
- g_virtbuf = g_drawbuf;
- }
- }
-
- /* set the color pallette */
-
- void EGA_setpal(p, v)
- unsigned p, v;
- {
- union REGS inregs, outregs;
-
- inregs.h.ah = ega_setpal;
- inregs.h.al = 0;
- inregs.h.bl = p;
- inregs.h.bh = v;
- int86(int_video, &inregs, &outregs);
- }
-
- /* set the background color - just use setpal() */
-
- void EGA_setback(c)
- unsigned c;
- {
- EGA_setpal(0, c);
- }
-
- /* turn on graphics mode. mode has no meaning */
-
- #ifdef __TURBOC__
- # pragma warn -par /* TC */
- #endif
- void EGA_gopen(mode)
- unsigned mode;
- {
- union REGS inregs, outregs;
-
- if (g_display == EN) { /* Enhanced color display */
- inregs.h.ah = ega_setmode;
- inregs.h.al = mde_640X350c;
- int86(int_video, &inregs, &outregs);
- g_page1addr = g_en_pg1;
- g_page2addr = g_en_pg2;
- g_bufsiz = g_en_bufsiz;
- g_colormask = g_en_colormask;
- g_xsize = g_en_xsize;
- g_ysize = g_en_ysize;
- g_xchsize = g_en_xchsize;
- g_ychsize = g_en_ychsize;
- g_aspect = g_en_aspect;
- }
- else if (g_display == CD) { /* Ordinary color display */
- inregs.h.ah = ega_setmode;
- inregs.h.al = mde_640X200c;
- int86(int_video, &inregs, &outregs);
- g_page1addr = g_cd_pg1;
- g_page2addr = g_cd_pg2;
- g_bufsiz = g_cd_bufsiz;
- g_colormask = g_cd_colormask;
- g_xsize = g_cd_xsize;
- g_ysize = g_cd_ysize;
- g_xchsize = g_cd_xchsize;
- g_ychsize = g_cd_ychsize;
- g_aspect = g_cd_aspect;
- }
- else if (g_display == MO) { /* Monochrome display */
- inregs.h.ah = ega_setmode; /* THIS HAS NOT BEEN TESTED */
- inregs.h.al = mde_640X350m;
- int86(int_video, &inregs, &outregs);
- g_page1addr = g_mo_pg1;
- g_page2addr = g_mo_pg2;
- g_bufsiz = g_mo_bufsiz;
- g_colormask = g_mo_colormask;
- g_xsize = g_mo_xsize;
- g_ysize = g_mo_ysize;
- g_xchsize = g_mo_xchsize;
- g_ychsize = g_mo_ychsize;
- g_aspect = g_mo_aspect;
- }
-
- g_physbuf = g_page1addr;
- g_virtbuf = g_page2addr;
- g_colormax = g_colormask;
- g_pages = 2;
- g_curpage = 0;
- }
- #ifdef __TURBOC__
- # pragma warn .par /* TC */
- #endif
-
- /* turn off graphics mode */
-
- void EGA_gclose()
- {
- union REGS inregs, outregs;
-
- inregs.h.ah = ega_setmode;
- inregs.h.al = mde_80co;
- int86(int_video, &inregs, &outregs);
- }
-
- /* setup for point plotting */
-
- void EGA_point_set(c)
- unsigned c;
- {
- trimcolor(c);
- outp(ega_gr_addr, ega_gr_sr); /* set/reset register */
- outp(ega_gr_data, c);
- outp(ega_gr_addr, ega_gr_sren); /* set/reset enable register */
- outp(ega_gr_data, g_colormask);
- outp(ega_gr_addr, ega_gr_mode); /* mode register */
- outp(ega_gr_data, 0); /* write mode 0 */
- outp(ega_gr_addr, ega_gr_rot);
- outp(ega_gr_data, g_xor ? ega_gr_x_xor : 0); /* set xor mode */
- outp(ega_gr_addr, ega_gr_mask); /* set graphics addr to map reg */
- }
-
- /* reset ega afterwards */
-
- void EGA_point_res()
- {
- outp(ega_gr_data, g_allmask); /* to map register */
- outp(ega_gr_addr, ega_gr_rot); /* reset ega */
- outp(ega_gr_data, 0);
- outp(ega_gr_addr, ega_gr_sren);
- outp(ega_gr_data, 0);
- }
-
- /* plot a point */
-
-
- /* This fine piece of code has now been supplanted by a weenie hunk
- of assembly..... */
- /* Well, in this case it really wasn't quite so fine but still... */
- /*
- void EGA_point(x1,y1,c)
- unsigned x1,y1,c;
- {
- long p;
- unsigned pixoff, offs;
- g_obj far *ptr;
- g_obj mask;
- register g_obj tmp;
-
- /* icky, icky, icky! *
-
- EGA_point_set(c);
-
- goffs(x1, y1, &offs, &pixoff);
- ptr = g_drawbuf + offs;
- mask = 1 << pixoff*g_bitpix;
- plot(ptr, mask, tmp); /* plot pt. *
-
- EGA_point_res();
- }
- */
- /* draw a line... */
-
- #ifdef __TURBOC__
- # pragma warn -aus /* TC */
- #endif
- void EGA_line(x1,y1,x2,y2,c)
- unsigned x1,y1,x2,y2,c;
- {
- unsigned pixoff, offs;
- g_obj far *ptr;
- int delx,dely;
- int xyswap=0;
- int ydir=0;
- int i,ydelx;
- g_obj mask;
- register g_obj tmp;
-
- EGA_point_set(c);
-
- if (x1 > x2) { /* sort into left-right order */
- register int tmp;
- tmp=x1; x1=x2; x2=tmp;
- tmp=y1; y1=y2; y2=tmp;
- }
- goffs(x1, y1, &offs, &pixoff);
- ptr = g_drawbuf+offs;
- mask = 1 << pixoff*g_bitpix;
- plot(ptr, mask, tmp); /* plot pt. */
- if (x1==x2 && y1==y2) { /* handle 1 pt. correctly */
- EGA_point_res();
- return;
- }
- delx=x2-x1;
- dely=y2-y1;
- if (dely < 0) { /* handle lines from up to down */
- ydir=1;
- dely=-dely;
- }
- if (abs(dely) > delx) { /* handle slopes > 1 */
- register int tmp;
- tmp=x1; x1=y1; y1=tmp;
- tmp=x2; x2=y2; y2=tmp;
- tmp=delx; delx=dely; dely=tmp;
- xyswap=1;
- }
- ydelx=0;
- for (i=1; i<=delx; i++) {
- if ((ydelx+=dely) >= delx) {
- bumpx(ptr, mask); /* bump both x & y */
- bumpy(ptr, ydir);
- ydelx-=delx;
- }
- else
- if (xyswap) /* bump x only */
- bumpy(ptr, ydir)
- else
- bumpx(ptr, mask);
- plot(ptr, mask, tmp); /* plot point, go around again */
- }
- EGA_point_res();
- }
- #ifdef __TURBOC__
- # pragma warn .aus /* TC */
- #endif
-
- /* since we're always writing to an EGA buffer, we can use the BIOS
- routine! */
-
- void EGA_writech(row, col, ch, c, page)
- unsigned row, col, c;
- char ch;
- int page;
- {
- union REGS inregs, outregs;
-
- inregs.h.ah = ega_setcur;
- inregs.h.dh = row;
- inregs.h.dl = col;
- inregs.h.bh = page >= 0 ? page : (g_drawbuf > g_page1addr ? 1 : 0);
- int86(int_video, &inregs, &outregs);
-
- inregs.h.ah = ega_writech;
- inregs.h.bh = page >= 0 ? page : (g_drawbuf > g_page1addr ? 1 : 0);
- inregs.x.cx = 1;
- inregs.h.al = ch;
- inregs.h.bl = c /*| (g_xor ? 0x80 : 0)*/;
- int86(int_video, &inregs, &outregs);
- }
-